home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
text
/
misc
/
nenscript1_3.lha
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-22
|
17KB
|
680 lines
/*
* $Id: main.c,v 1.3 1992/10/07 22:06:08 craigs Exp $
*
* This code was written by Craig Southeren whilst under contract
* to Computer Sciences of Australia, Systems Engineering Division.
* It has been kindly released by CSA into the public domain.
*
* Neither CSA or me guarantee that this source code is fit for anything,
* so use it at your peril. I don't even work for CSA any more, so
* don't bother them about it. If you have any suggestions or comments
* (or money, cheques, free trips =8^) !!!!! ) please contact me
* care of geoffw@extro.ucc.oz.au
*
*/
#include "machdep.h"
#include "defs.h"
#include "version.h"
#include "print.h"
#include "main.h"
#include "paper.h"
#include "postscri.h"
/********************************
defines
********************************/
/* environment variables */
#define PRINTER "PRINTER" /* sets name of printer */
#define NENSCRIPT "NENSCRIPT" /* contains options */
/********************************
exports
********************************/
char *progname;
/********************************
usage
********************************/
void usage ()
{
printf ("usage: %s -?12BGghlNnRrSsVWwZ -f font -F titlefont -b header -i filetitle -L lines -p filename -P printer -S classification -T papertype -t tabstop -# copies file...\n", progname);
exit (0);
}
/*********************************
variables set by options
*********************************/
static int landscape = False; /* True if in ladnscape mode, i.e. -r specified */
static int columns = 1; /* number of columns to print with */
static char *outputfilename = NULL; /* name of output file, if still NULL after parsing args then use lpr */
static char *bodyfont = NULL; /* font to use for text */
static char *titlefont = NULL; /* font to use for titles */
static int wrap = True; /* True if to wrap long lines */
static int titlesenabled = True; /* True if page titles enables */
static char *title = NULL; /* set to title if specified */
static int copies = 1; /* number of copies of each page */
static int gaudy = False; /* enables gaudy mode */
static int force_lines = 0; /* force number of lines per page */
static char *classification = NULL; /* security classification */
static int line_numbers = False; /* true if to display line numbers */
static char *printername = DEF_PRINTER; /* name of printer to use when output goes to lpr */
static int tabstop = 8; /* tab stops */
static int passthroughflag = False; /* if True, then check for %! to allow passthrough of raw postscript */
static char *filetitle = NULL; /* set file title */
#ifdef US_VERSION
static char *papertype = "US";
#else
static char *papertype = "A4";
#endif
/*
* forward declarations if in ANSI mode
*/
#ifdef __STDC__
char * get_string (char **);
void parse_options (int *, char ***);
void parse_env (char *);
#endif
/********************************
parse_options
********************************/
#define ARGC (*argc)
#define ARGV (*argv)
void parse_options (argc, argv)
int *argc;
char ***argv;
{
char c;
char *s;
int i;
/* parse the options */
next_argv:
while (--ARGC > 0 && (*++ARGV)[0] == '-')
while (c = *++ARGV[0])
switch (c) {
/* -? : print help message */
case '?' :
case 'h' :
usage ();
break;
/* -1 : single column mode */
case '1' :
columns = 1;
break;
/* -2 : double column mode */
case '2' :
columns = 2;
break;
/* -#: set number of copies */
case '#' :
if (*++ARGV[0])
copies = atoi (ARGV[0]);
else {
if (ARGC < 1)
fprintf (stderr, "%s: -# option requires argument\n", progname);
else {
--ARGC;
copies = atoi (*++ARGV);
}
}
if (copies < 1) {
fprintf (stderr, "%s: illegal number of copies specified - defaulting to one\n", progname);
copies = 1;
}
goto next_argv;
break;
/* -b: set page title */
case 'b' :
if (*++ARGV[0])
title = ARGV[0];
else {
if (ARGC < 1)
fprintf (stderr, "%s: -b option requires argument\n", progname);
else {
--ARGC;
title = *++ARGV;
}
}
goto next_argv;
break;
/* -f : set font to use for printing body */
case 'f' :
if (*++ARGV[0])
bodyfont = ARGV[0];
else {
if (ARGC < 1)
fprintf (stderr, "%s: -f option requires argument\n", progname);
else {
--ARGC;
bodyfont = *++ARGV;
}
}
goto next_argv;
break;
/* -N : display line numbers */
case 'N' :
line_numbers = True;
break;
/* -n : disable line numbers */
case 'n' :
line_numbers = False;
break;
/* -p: send to file rather than lpr */
case 'p' :
if (*++ARGV[0])
outputfilename = ARGV[0];
else {
if (ARGC < 1)
fprintf (stderr, "%s: -p option requires argument\n", progname);
else {
--ARGC;
outputfilename = *++ARGV;
}
}
goto next_argv;
break;
/* -r : landscape mode */
case 'r' :
landscape = True;
break;
/* -w : wrap mode */
case 'w' :
wrap = True;
break;
/* -Z : check for postscript passthrough mode */
case 'Z' :
passthroughflag = True;
break;
/* -B : disable page headings and disable gaudy mode */
case 'B' :
titlesenabled = False;
break;
/* -F : set font to use for printing titles */
case 'F' :
if (*++ARGV[0])
titlefont = ARGV[0];
else {
if (ARGC < 1)
fprintf (stderr, "%s: -F option requires argument\n", progname);
else {
--ARGC;
titlefont = *++ARGV;
}
}
goto next_argv;
break;
/* -g : disable gaudy mode */
case 'g' :
gaudy = False;
break;
/* -G : enable gaudy mode */
case 'G' :
gaudy = True;
break;
/* -i: set file title when inputting from stdin */
case 'i' :
if (*++ARGV[0])
filetitle = ARGV[0];
else {
if (ARGC < 1)
fprintf (stderr, "%s: -i option requires argument\n", progname);
else {
--ARGC;
filetitle = *++ARGV;
}
}
goto next_argv;
break;
/* -l : don't set number of lines of page, i.e. use maximum */
case 'l' :
force_lines = 0;
break;
/* -L : force number of lines per page */
case 'L' :
if (*++ARGV[0])
force_lines = atoi(ARGV[0]);
else {
if (ARGC < 1)
fprintf (stderr, "%s: -x option requires argument\n", progname);
else {
--ARGC;
force_lines = atoi (*++ARGV);
}
}
if (force_lines <= 0) {
fprintf (stderr, "%s: ignoring illegal arguement to -L option\n", progname);
force_lines = 0;
}
goto next_argv;
break;
/* -P: set printer name - overrides PRINTER environment variables */
case 'P' :
if (*++ARGV[0])
printername = ARGV[0];
else {
if (ARGC < 1)
fprintf (stderr, "%s: -P option requires argument\n", progname);
else {
--ARGC;
printername = *++ARGV;
}
}
goto next_argv;
break;
/* -R : portrait mode */
case 'R' :
landscape = False;
break;
/* -S: set security classification */
case 'S' :
if (*++ARGV[0])
classification = ARGV[0];
else {
if (ARGC < 1)
fprintf (stderr, "%s: -S option requires argument\n", progname);
else {
--ARGC;
classification = *++ARGV;
}
}
goto next_argv;
break;
/* -s : disable security classification printing */
case 's' :
classification = NULL;
break;
/* -T: set paper size to either US or A4 */
case 'T' :
if (*++ARGV[0])
papertype = ARGV[0];
else {
if (ARGC < 1)
fprintf (stderr, "%s: -T option requires argument\n", progname);
else {
--ARGC;
papertype = *++ARGV;
}
}
goto next_argv;
break;
/* -t: set tab stop size */
case 't' :
if (*++ARGV[0])
s = ARGV[0];
else {
if (ARGC < 1) {
fprintf (stderr, "%s: -t option requires argument\n", progname);
s = 0; /* We should flag the error in some way */
} else {
--ARGC;
s = *++ARGV;
}
}
if ((i = atoi (s)) <= 0)
fprintf (stderr, "%s: illegal tab setting %s ignored\n", progname, s);
else
tabstop = i;
goto next_argv;
break;
/* -V : print version number */
case 'V' :
fputs (version_string, stderr);
fputs ("\n", stderr);
/* fputs (copyright_string, stderr); */
exit (0);
break;
/* -W : turn off wrap mode */
case 'W' :
wrap = False;
break;
/* single char option */
/* case 'x' :
allow_checkouts = True;
break;
*/
/* option with string */
/* case 'x' :
if (*++ARGV[0])
optionstring = ARGV[0];
else {
if (ARGC < 1)
fprintf (stderr, "%s: -x option requires argument\n", progname);
else {
--ARGC;
optionstring = *++ARGV;
}
}
goto next_argv;
break;
*/
default :
fprintf (stderr, "%s: unknown option %c\n", progname, c);
ARGC = 0;
break;
}
}
/********************************
get_string
return the next string from the argument
********************************/
char * get_string (str)
char **str;
#define STR (*str)
{
char *ret = NULL;
int in_dquote, in_squote, in_bquote;
int quote_count;
/* skip leading whitespace */
while (*STR == ' ' ||
*STR == '\t')
STR++;
/* return if end of string */
if (*STR == '\0')
return NULL;
/* collect characters until end of string or whitespace */
in_dquote = -1;
in_squote = -1;
in_bquote = -1;
quote_count = 0;
ret = STR;
while (*STR != '\0' &&
(quote_count > 0 || (*STR != ' ' && *STR != '\t'))
) {
switch (*STR) {
case '"':
in_dquote = -in_dquote;
quote_count += in_dquote;
break;
case '\'':
in_squote = -in_squote;
quote_count += in_squote;
break;
case '`':
in_bquote = -in_bquote;
quote_count += in_bquote;
break;
case '\\':
if (STR[1] != '\0')
STR++;
break;
}
STR++;
}
if (*STR != '\0') {
*STR = '\0';
STR++;
}
if (quote_count > 0)
fprintf (stderr, "unmatched quote in %s environment variable\n", NENSCRIPT);
return ret;
}
/********************************
parse_env
process the options specified in the supplied string
********************************/
void parse_env (env)
char *env;
{
int argc;
char *s;
char **argv;
if (env == NULL)
return;
/* insert a "fake" argv[0] which corresponds to the real
argv[0] passed to main. The allows us to use same routine
for handling the real arguments */
argv = (char **)malloc (sizeof (char *));
argc = 1;
argv[0] = progname;
/* split the single environment string into separate strings so we can pass
them to parse_options */
while ((s = get_string (&env)) != NULL) {
argv = (char **)realloc ((void *)argv, (argc+1) * sizeof (char *));
argv[argc] = s;
argc++;
}
/* parse the options */
parse_options (&argc, &argv);
}
/********************************
passthrough
********************************/
static void passthrough (input, output)
FILE * input;
FILE * output;
{
char buff [512];
int len;
while ((len = fread (buff, 1, 512, input)) > 0)
fwrite (buff, 1, len, output);
}
/********************************
main
********************************/
int main (argc, argv)
int argc;
char *argv[];
{
char *env;
char cmd[1024];
struct PaperMetrics * papermetrics;
int i;
int ch1;
int ch2;
FILE *outputstream; /* opened output stream - either file or lpr */
FILE *inputstream; /* opened input stream, 0 if max */
/* extract the program name */
if ((progname = strrchr (argv[0], '/')) == NULL)
progname = argv[0];
else
progname++;
/* get the printer environment variable */
if ((env = getenv (PRINTER)) != NULL)
printername = env;
/* handle the NENSCRIPT environment variable */
if ((env = getenv (NENSCRIPT)) != NULL)
parse_env (STRDUP(env));
/* parse arguments */
parse_options (&argc, &argv);
/* open either the output file or a pipe to lpr */
if (outputfilename != NULL) {
if (strcmp (outputfilename, "-") == 0)
outputstream = stdout;
else if ((outputstream = fopen (outputfilename, "w")) == NULL) {
perror (outputfilename);
exit (1);
}
} else {
#ifdef MSDOS
if ((outputstream = fopen (printername, "w")) == NULL) {
perror (printername);
exit (1);
}
#else /* MSDOS */
#ifdef AMIGA
if ((outputstream = fopen ("LPR:", "w")) == NULL) {
perror ("lpr:");
exit (1);
}
#else /* Amiga */
sprintf (cmd, "%s %s", LPR, printername);
if ((outputstream = popen (cmd, "w")) == NULL) {
perror (LPR);
exit (1);
}
#endif /* Amiga */
#endif /* MSDOS */
}
/* can't be in passthrough mode with more than one argument */
if (argc > 1 && passthroughflag) {
fprintf (stderr, "%s: ignoring -Z flag as there is more than one argument", progname);
passthroughflag = False;
}
/* if in passthrough mode, open the input stream and check for %! */
if (passthroughflag) {
if (argc < 1)
inputstream = stdin;
else if ((inputstream = fopen (*argv, "r")) == NULL) {
perror (*argv);
exit (1);
}
ch1 = fgetc (inputstream);
ch2 = fgetc (inputstream);
ungetc (ch2, inputstream);
ungetc (ch1, inputstream);
if (ch1 == '%' && ch2 == '!') {
passthrough (inputstream, outputstream);
exit (0);
}
} else
inputstream = NULL;
/* check the paper type and get ptr to record */
papermetrics = NULL;
for (i = 0; PaperTypes[i].Name != NULL; i++)
if (STRICMP ((papermetrics = &PaperTypes[i])->Name, papertype) == 0)
break;
/* if the papermetric was not set, give error */
if (PaperTypes[i].Name == NULL) {
fprintf (stderr, "%s: paper type %s not known\n", progname, papertype);
exit (1);
}
/* set up the fonts */
if (bodyfont == NULL)
bodyfont = (columns == 2 && landscape) ? papermetrics->LandscapeFont : papermetrics->PortraitFont;
if (titlefont == NULL)
titlefont = papermetrics->TitleFont;
/* display the header */
StartJob (outputstream,
*argv,
landscape,
columns,
bodyfont,
titlefont,
wrap,
titlesenabled,
title,
copies,
gaudy,
force_lines,
classification,
papermetrics,
tabstop);
/* if no arguments, then accept stdin */
if (argc < 1)
print_file (stdin, outputstream, (filetitle ? filetitle : "stdin"), line_numbers);
else for (;argc > 0;argc--) {
if (inputstream == NULL && (inputstream = fopen (*argv, "r")) == NULL)
perror (*argv);
else {
print_file (inputstream, outputstream, (filetitle ? filetitle : *argv), line_numbers);
fclose(inputstream);
inputstream = NULL;
}
argv++;
}
/* output trailer */
EndJob (outputstream);
/* finished */
return (0);
}